package org.lanyu.springainovel.novel.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lanyu.springainovel.chat.service.PromptTemplateService;
import org.lanyu.springainovel.common.config.ChatModelManager;
import org.lanyu.springainovel.common.entity.MyPromptTemplate;
import org.lanyu.springainovel.novel.entity.BookOutline;
import org.lanyu.springainovel.novel.mapper.NovelOutlineMapper;
import org.lanyu.springainovel.novel.service.BookService;
import org.lanyu.springainovel.novel.service.NovelOutlineService;
import org.lanyu.springainovel.novel.vo.NovelOutlineRequest;
import org.lanyu.springainovel.novel.vo.OutlineUpdateRequest;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 小说大纲服务实现类
 */
@Slf4j
@Service
@AllArgsConstructor
public class NovelOutlineServiceImpl extends ServiceImpl<NovelOutlineMapper, BookOutline> implements NovelOutlineService {

    private final ChatModelManager chatModelManager;
    private final PromptTemplateService promptTemplateService;
    private final ObjectMapper objectMapper;
    private final BookService bookService;

    /**
     * 流式生成小说大纲
     *
     * @param request 大纲生成请求
     * @return 流式大纲内容
     */
    @Override
    public Flux<String> generateNovelOutlineStream(NovelOutlineRequest request) {
        try {
            // 1. 验证请求参数
            if (request.getSystemPromptId() == null) {
                return Flux.just("系统提示词模板ID不能为空");
            }

            if (request.getModelId() == null) {
                return Flux.just("模型ID不能为空");
            }

            // 2. 获取AI模型
            ChatModel chatModel = chatModelManager.getOrCreateChatModelById(request.getModelId());
            if (chatModel == null) {
                return Flux.just("无法创建聊天模型");
            }

            // 3. 获取系统提示词（不包含结构化输出指令）
            String systemPrompt = getSystemPrompt(request.getSystemPromptId());
            if (systemPrompt == null) {
                return Flux.just("无法获取系统提示词模板");
            }

            // 4. 构建用户提示词
            String userPrompt = buildStreamUserPrompt(request);

            // 5. 创建ChatClient
            ChatClient chatClient = ChatClient.builder(chatModel).build();

            // 6. 生成流式响应
            return chatClient.prompt()
                    .system(systemPrompt)
                    .user(userPrompt)
                    .stream()
                    .content()
                    .doOnError(error -> log.error("生成大纲流式响应失败", error))
                    .onErrorResume(error -> Flux.just("生成大纲失败: " + (error.getMessage() != null ? error.getMessage() : "未知错误")));
        } catch (Exception e) {
            log.error("生成大纲失败", e);
            return Flux.just("生成大纲失败: " + e.getMessage());
        }
    }

    /**
     * 获取系统提示词（不包含结构化输出指令）
     *
     * @param systemPromptId 系统提示词ID
     * @return 系统提示词
     */
    private String getSystemPrompt(Long systemPromptId) {
        if (systemPromptId == null) {
            return null;
        }

        // 从服务获取提示词模板
        MyPromptTemplate promptTemplate = promptTemplateService.getTemplateById(systemPromptId);
        if (promptTemplate == null || promptTemplate.getContent() == null || promptTemplate.getContent().isEmpty()) {
            return null;
        }

        String systemPrompt = promptTemplate.getContent();

        // 增加模板使用次数
        promptTemplateService.incrementUsageCount(systemPromptId);

        // 不添加结构化输出指令，让AI自由生成文本格式的大纲
        return systemPrompt;
    }

    /**
     * 构建流式生成的用户提示词
     *
     * @param request 大纲生成请求
     * @return 用户提示词
     */
    private String buildStreamUserPrompt(NovelOutlineRequest request) {
        StringBuilder promptBuilder = new StringBuilder();

        // 添加用户提示词
        if (request.getUserPrompt() != null && !request.getUserPrompt().trim().isEmpty()) {
            promptBuilder.append("小说描述：").append(request.getUserPrompt()).append("\n\n");
        }

        return promptBuilder.toString();
    }

    /**
     * 根据书籍ID获取最新版本大纲
     *
     * @param bookId 书籍ID
     * @return
     */
    @Override
    public BookOutline getOutlineByBookId(Long bookId) {
        LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BookOutline::getBookId, bookId)
                .orderByDesc(BookOutline::getVersion)
                .last("LIMIT 1");
        return getOne(queryWrapper);
    }


    /**
     * 根据书籍ID获取最新版本大纲
     *
     * @param bookId 书籍ID
     * @return
     */
    @Override
    public BookOutline getOutlineByBookVersion(Long bookId, Long version) {
        LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BookOutline::getBookId, bookId)
                .eq(BookOutline::getVersion, version)
                .orderByDesc(BookOutline::getCreateTime)
                .last("LIMIT 1");
        return getOne(queryWrapper);
    }

    /**
     * 返回大纲所有版本列表
     *
     * @param bookId 书籍ID
     * @return
     */
    @Override
    public List<BookOutline> getOutlinesByBookIdOrderByVersionDesc(Long bookId) {
        LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(BookOutline::getId, BookOutline::getBookId, BookOutline::getVersion,BookOutline::getRemark,
                        BookOutline::getIsActive, BookOutline::getCreateTime, BookOutline::getUpdateTime)
                .eq(BookOutline::getBookId, bookId)
                .orderByDesc(BookOutline::getVersion);
        return list(queryWrapper);
    }

    /**
     * 保存或更新大纲信息
     *
     * @param newOutline 大纲信息
     * @return 新增或更新后的大纲信息
     */
    @Override
    public BookOutline saveOrUpdateOutline(OutlineUpdateRequest newOutline) {
        //区分更新还是新增
        if (newOutline.getId() == null) {
            // 新增大纲
            BookOutline bookOutline = new BookOutline();
            bookOutline.setBookId(newOutline.getBookId());
            bookOutline.setOutlineDetails(newOutline.getOutlineDetails());
            bookOutline.setChapterPlanning(newOutline.getChapterPlanning());
            bookOutline.setSubPlots(newOutline.getSubPlots());

            bookOutline.setIsActive(0); // 默认为非启用状态

            // 查询当前书籍的最大版本号
            LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookOutline::getBookId, newOutline.getBookId())
                    .orderByDesc(BookOutline::getVersion)
                    .last("LIMIT 1");
            BookOutline latestOutline = getOne(queryWrapper);

            // 设置版本号为最大版本+1，如果没有现有版本则设置为1
            Integer newVersion = (latestOutline != null && latestOutline.getVersion() != null)
                    ? latestOutline.getVersion() + 1 : 1;
            bookOutline.setVersion(newVersion);
            bookOutline.setRemark("新建大纲v"+newVersion);
            
            boolean saved = this.saveOrUpdate(bookOutline);
            if (!saved) {
                throw new RuntimeException("保存大纲失败");
            }
            
            return bookOutline;
        } else {
            // 更新现有大纲
            BookOutline oldOutline = this.getById(newOutline.getId());
            oldOutline.setOutlineDetails(newOutline.getOutlineDetails());
            oldOutline.setChapterPlanning(newOutline.getChapterPlanning());
            oldOutline.setSubPlots(newOutline.getSubPlots());
            
            // 更新备注信息
            // 不论remark是否为空，都进行更新
            oldOutline.setRemark(newOutline.getRemark());

            // 处理isActive字段
            if (newOutline.getIsActive() != null) {
                // 如果要设置为启用状态，需要先将同一本书的所有大纲设置为非启用状态
                if (newOutline.getIsActive() == 1 && (oldOutline.getIsActive() == null || oldOutline.getIsActive() != 1)) {
                    LambdaQueryWrapper<BookOutline> updateWrapper = new LambdaQueryWrapper<>();
                    updateWrapper.eq(BookOutline::getBookId, oldOutline.getBookId());
                    BookOutline updateOutline = new BookOutline();
                    updateOutline.setIsActive(0);
                    this.update(updateOutline, updateWrapper);
                }
                oldOutline.setIsActive(newOutline.getIsActive());
            }

            boolean updated = this.saveOrUpdate(oldOutline);
            if (!updated) {
                throw new RuntimeException("更新大纲失败");
            }
            
            return oldOutline;
        }
    }

    @Override
    public BookOutline getOutlineById(Long id) {
        return this.getById(id);
    }

    @Override
    public boolean deleteOutlineAndChapters(Long bookId, Long userId) {
        try {
            // 查询所有版本的大纲
            LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookOutline::getBookId, bookId);
            List<BookOutline> outlines = list(queryWrapper);

            if (!outlines.isEmpty()) {
                // 删除所有版本的大纲
                for (BookOutline outline : outlines) {
                    removeById(outline.getId());
                }
                log.info("已删除书籍ID: {} 的所有版本大纲，共{}个版本", bookId, outlines.size());
            }

            return true;
        } catch (Exception e) {
            log.error("删除大纲失败", e);
            throw new RuntimeException("删除大纲失败: " + e.getMessage());
        }
    }

    /**
     * 删除指定版本的大纲
     *
     * @param bookId  书籍ID
     * @param version 版本号
     * @return 删除成功
     */
    @Override
    public boolean deleteOutlineByVersion(Long bookId, Long version) {
        try {
            // 查询指定版本的大纲
            LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookOutline::getBookId, bookId)
                    .eq(BookOutline::getVersion, version);
            BookOutline outline = getOne(queryWrapper);

            if (outline == null) {
                log.warn("未找到书籍ID: {} 版本: {} 的大纲", bookId, version);
                return true; // 如果不存在，视为删除成功
            }

            // 删除指定版本的大纲
            boolean deleted = removeById(outline.getId());
            if (!deleted) {
                throw new RuntimeException("删除大纲失败");
            }

            log.info("已删除书籍ID: {} 版本: {} 的大纲", bookId, version);
            return true;
        } catch (Exception e) {
            log.error("删除指定版本大纲失败", e);
            throw new RuntimeException("删除指定版本大纲失败: " + e.getMessage());
        }
    }

    /**
     * 归档大纲，创建新版本
     *
     * @param bookId          书籍ID
     * @param outlineDetails  大纲内容
     * @param chapterPlanning 章节规划
     * @return 新创建的大纲信息
     */
    @Override
    public BookOutline archiveOutline(Long bookId, String outlineDetails, String chapterPlanning, Integer version) {
        try {
            // 查询当前版本
            LambdaQueryWrapper<BookOutline> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookOutline::getBookId, bookId)
                    .orderByDesc(BookOutline::getVersion)
                    .last("LIMIT 1");
            BookOutline latestOutline = getOne(queryWrapper);

            // 创建新版本的大纲
            BookOutline newOutline = new BookOutline();
            newOutline.setBookId(bookId);
            newOutline.setOutlineDetails(outlineDetails);
            newOutline.setChapterPlanning(chapterPlanning);
            newOutline.setCreateTime(LocalDateTime.now());
            newOutline.setUpdateTime(LocalDateTime.now());
            newOutline.setStatus(1); // 默认状态为草稿

            // 设置版本号为当前最大版本+1，如果没有现有版本则设置为1
            Integer newVersion = (latestOutline != null && latestOutline.getVersion() != null)
                    ? latestOutline.getVersion() + 1 : version;
            newOutline.setVersion(newVersion);

            // 保存新版本
            boolean saved = save(newOutline);
            if (!saved) {
                throw new RuntimeException("保存归档大纲失败");
            }

            log.info("已归档书籍ID: {} 的大纲，新版本号: {}", bookId, newVersion);
            return newOutline;
        } catch (Exception e) {
            log.error("归档大纲失败", e);
            throw new RuntimeException("归档大纲失败: " + e.getMessage());
        }
    }
}